package com.caseProject.puremvc.model
{
	import com.caseProject.puremvc.model.business.FileManager;
	import com.caseProject.puremvc.model.events.FileManagerEvent;
	import com.caseProject.puremvc.model.vo.DiagramActivityVO;
	import com.caseProject.puremvc.model.vo.DiagramStateVO;
	import com.caseProject.puremvc.model.vo.ElementVO;
	import com.caseProject.puremvc.model.vo.PartitionVO;
	import com.caseProject.puremvc.model.vo.TransitionVO;
	import com.caseProject.puremvc.notifications.NotificationNames;
	
	import flash.events.Event;
	
	import org.puremvc.as3.interfaces.IProxy;
	import org.puremvc.as3.patterns.proxy.Proxy;
	
	public class ProjectProxy extends Proxy implements IProxy
	{
		public static const NAME:String = "ProjectProxy";
		
		private var fileManager:FileManager;
		private var diagramList:Vector.<Diagram>;
		private var _currentDiagram:Diagram;
		
		public function ProjectProxy(data:Object=null)
		{
			super(NAME, data);
			this.fileManager = FileManager.getInstance();	
			this.diagramList = new Vector.<Diagram>();
		}
		
		public function get currentDiagram():Diagram
		{
			return _currentDiagram;
		}

		/**
		 * Request FileManager to create a new project
		 * */
		public function createFile ():void
		{
			this.diagramList = new Vector.<Diagram>();
			this.fileManager.createFile();
			this.sendNotification(NotificationNames.CREATE_PROJECT_SUCESS);
		}
		
		/**
		 * Request FileManager to save an open project
		 * */
		public function saveFile():void
		{
			this.fileManager.saveFile(this.diagramList);
		}
		
		/**
		 * Request FileManager to open a select project
		 * */
		public function openFile():void
		{
			this.fileManager.openFile();			
			this.fileManager.addEventListener(FileManagerEvent.LOAD_DATA_SUCCESS, onDataLoad);			
		}
		
		/**
		 * Called when FileManager parses xml project file to a Diagram list 
		 * */
		private function onDataLoad(e:FileManagerEvent):void
		{
			this.diagramList = e.diagramList;
			this.sendNotification(NotificationNames.OPEN_PROJECT_SUCESS, this.diagramList);
		}
		
		public function openDiagram (diagram:Diagram):void
		{
			this._currentDiagram = diagram;
		}
		
		public function removeDiagram(diagramVO:Diagram):void
		{
			for (var i:int = 0; i < this.diagramList.length; i++) 
			{
				if (diagramVO == this.diagramList[i])
				{
					this.diagramList.splice(i,1);
					break;
				}
			}
		}
		
		public function createDiagram (type:String):void
		{
			switch (type){
				case DiagramNames.STATE:
					var diagramStateVO:DiagramStateVO = new DiagramStateVO();
					diagramStateVO.name = "State Diagram";
					
					this.diagramList.push(diagramStateVO);
					this._currentDiagram = diagramStateVO;
					
					this.sendNotification(NotificationNames.CREATE_DIAGRAM_SUCESS, this.diagramList);
					break;
				
				case DiagramNames.ACTIVITY:
					var diagramActivityVO:DiagramActivityVO = new DiagramActivityVO();
					diagramActivityVO.name = "Activity Diagram";
					
					this.diagramList.push(diagramActivityVO);
					this._currentDiagram = diagramActivityVO;
					
					this.sendNotification(NotificationNames.CREATE_DIAGRAM_SUCESS, this.diagramList);
					break;
				
				default:
					throw new Error ("DiagramProxy: Diagram Type Not Found");
			}
		}
		
		private function retrieveDiagramClass():Class
		{
			var DClass:Class;
			if (this._currentDiagram.type == DiagramNames.STATE)
			{
				DClass = DiagramStateVO;
			}
			else if (this._currentDiagram.type == DiagramNames.ACTIVITY)
			{
				DClass = DiagramActivityVO;
			}
			else {
				throw new Error("Diagram not found");
			}
			
			return DClass;
		}
		
		public function deleteGraphicElement(graphicVO:ElementVO):void
		{
			var DClass:Class = this.retrieveDiagramClass();
			
			for (var i:int = 0; i < DClass(this._currentDiagram).elements.length; i++)
			{
				if (DClass(this._currentDiagram).elements[i] == graphicVO)
				{
					DClass(this._currentDiagram).elements.splice(i,1);
				}
			}
		}
		
		public function deleteGraphicPartition(graphicVO:PartitionVO):void
		{
			var DClass:Class = this.retrieveDiagramClass();
			var partitionVOList:Vector.<PartitionVO> = DClass(this._currentDiagram).partitions;
			
			for (var i:int = 0; i < partitionVOList.length; i++)
			{
				if (partitionVOList[i] == graphicVO)
				{
					partitionVOList.splice(i,1);
				}
			}			
		}
		
		public function deleteGraphicTransition(graphicVO:TransitionVO):void
		{
			var DClass:Class = this.retrieveDiagramClass();
			var transitionVOList:Vector.<TransitionVO> = (this._currentDiagram as DClass).transitions;
			
			for (var i:int = 0; i < transitionVOList.length; i++)
			{
				if (transitionVOList[i] == graphicVO)
				{
					transitionVOList.splice(i,1);
				}
			}			
		}
		
		public function retrieveLinkedTransitions(graphicVO:ElementVO):void
		{
			var DClass:Class = this.retrieveDiagramClass();
			var transitions:Vector.<TransitionVO> = DClass(this._currentDiagram).transitions;
			
			var returnTransitions:Vector.<TransitionVO> = new Vector.<TransitionVO>();
			
			for (var i:int = 0; i < transitions.length; i++) 
			{
				if (transitions[i].elementFromId == graphicVO.id || transitions[i].elementToId == graphicVO.id)
				{
					returnTransitions.push(transitions[i]);
				}
			}			
			this.sendNotification(NotificationNames.RETRIEVE_LINKED_TRANSITIONS_SUCCESS, returnTransitions);
		}
		
		public function closeProject():void
		{
			this.diagramList = new Vector.<Diagram>();
			this.fileManager.resetDiagramList();
			this.sendNotification(NotificationNames.CLOSE_PROJECT_SUCESS);
		}
	}
}